{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import string\n",
    "import random\n",
    "from PIL import Image, ImageDraw, ImageFont\n",
    "\n",
    "\n",
    "# pillow是PIL（Python成像库）的一个分支，它不再被维护。所以，为了保持向后兼容性，\n",
    "# 往往使用旧的模块名称——PIL。所以，我们直接import PIL就可以了。\n",
    "\n",
    "class Captcha:\n",
    "    '''\n",
    "    :param captcha_size:图片验证码的尺寸\n",
    "    :param font_size:验证字体的大小\n",
    "    :param text_number:验证码的字符数\n",
    "    :param line_number:干扰线条数量\n",
    "    :param background_color:图片背景色\n",
    "    :param sources:取样字符集\n",
    "    :param save_format:图片保存格式\n",
    "    :return:\n",
    "    '''\n",
    "\n",
    "    def __init__(self, captcha_size=(150, 80),\n",
    "                 font_size=40, text_number=4,\n",
    "                 line_number=6, background_color=(255, 255, 255),\n",
    "                 sources=None, save_format='png'):\n",
    "\n",
    "        self.captcha_size = captcha_size\n",
    "        self.font_size = font_size\n",
    "        self.text_number = text_number\n",
    "        self.line_number = line_number\n",
    "        self.background_color = background_color\n",
    "        self.format = save_format\n",
    "        if sources:\n",
    "            self.sources = sources\n",
    "        else:\n",
    "            self.sources = string.ascii_letters + string.digits\n",
    "\n",
    "    def get_text(self):\n",
    "        # 从sources字符集里面根据验证码数量随机生成一串字符\n",
    "        text = random.sample(self.sources, k=self.text_number)\n",
    "        return ''.join(text)\n",
    "\n",
    "    def get_font_color(self):\n",
    "        # 随机获取验证码中的字符的RGB颜色\n",
    "        font_color = (random.randint(0, 150), random.randint(0, 150), random.randint(0, 150))\n",
    "        return font_color\n",
    "\n",
    "    def get_line_color(self):\n",
    "        line_color = (random.randint(0, 250), random.randint(0, 250), random.randint(0, 250))\n",
    "        return line_color\n",
    "\n",
    "    def draw_text(self, draw, text, font, captcha_width, captcha_height, spacing=20):\n",
    "        '''\n",
    "        在图片上绘制传入的字符\n",
    "        :param draw: 生成的画笔对象\n",
    "        :param text: 绘制的字符\n",
    "        :param font: 采用的字体\n",
    "        :param captcha_width:验证码宽度\n",
    "        :param captcha_height: 验证码高度\n",
    "        :param spacing: 字符之间间隔\n",
    "        :return:\n",
    "        '''\n",
    "        # 获得字符串的宽度,高度\n",
    "        text_width, text_height = font.getsize(text)\n",
    "        # 每个字符的大概宽度\n",
    "        every_value_width = int(text_width / 4)\n",
    "\n",
    "        # 这一串字符的总长度\n",
    "        text_length = len(text)\n",
    "        # 每两个字符之间拥有间隙,获取总的间隙???\n",
    "        total_spacing = (text_length - 1) * spacing\n",
    "\n",
    "        if total_spacing + text_width >= captcha_width:\n",
    "            raise ValueError('字体加中间空隙超过图片总宽度')\n",
    "\n",
    "        # 获取第一个字符绘制位置\n",
    "        start_width = int(captcha_width - text_width - total_spacing)\n",
    "        start_height = int((captcha_height - text_height) / 2)\n",
    "\n",
    "        # 依次绘制每个字符\n",
    "        for value in text:\n",
    "            position = start_width, start_height\n",
    "            print(position)\n",
    "            # 绘制text\n",
    "            draw.text(position, value, font=font, fill=self.get_font_color())\n",
    "            # 改变下一个字符的起始绘制\n",
    "            start_width = start_width + every_value_width + spacing\n",
    "\n",
    "    def draw_line(self, draw, captcha_width, captcha_height):\n",
    "        '''\n",
    "        绘制线条\n",
    "        :param draw:画笔对象\n",
    "        :param captcha_width:验证码宽度\n",
    "        :param captcha_height: 验证码高度\n",
    "        :return:\n",
    "        '''\n",
    "        # 随即获取开始位置的坐标\n",
    "        begin = (random.randint(0, captcha_width / 2), random.randint(0, captcha_height / 2))\n",
    "        # 随机获取结束位置的坐标\n",
    "        end = (random.randint(captcha_width / 2, captcha_width), random.randint(captcha_height / 2, captcha_height))\n",
    "        draw.line([begin, end], fill=self.get_line_color())\n",
    "\n",
    "    def draw_point(self, draw, point_chance, width, height):\n",
    "        '''\n",
    "        绘制干扰圆点\n",
    "        :param draw: 画笔对象\n",
    "        :param point_chance:绘制圆点的概率,point_chance / 100\n",
    "        :param width: 验证码宽度\n",
    "        :param height: 验证码高度\n",
    "        :return:\n",
    "        '''\n",
    "\n",
    "        # 按照概率随机绘制小圆点\n",
    "        for w in range(width):\n",
    "            for h in range(height):\n",
    "                tmp = random.randint(0, 100)\n",
    "                if tmp < point_chance:\n",
    "                    draw.point((w, h), fill=self.get_line_color())\n",
    "\n",
    "    def make_captcha(self):\n",
    "        # 制作验证码\n",
    "        # 获取验证码的宽度,高度\n",
    "        width, height = self.captcha_size\n",
    "        # 生成一张图片\n",
    "        captcha = Image.new('RGB', self.captcha_size, self.background_color)\n",
    "        # 获取字体对象\n",
    "        font = ImageFont.truetype('simkai.ttf', self.font_size)\n",
    "        # 获取画笔对象\n",
    "        draw = ImageDraw.Draw(captcha)\n",
    "        # 得到绘制的字符\n",
    "        text = self.get_text()\n",
    "\n",
    "        # 绘制字符\n",
    "        self.draw_text(draw, text, font, width, height)\n",
    "\n",
    "        # 绘制线条\n",
    "        for i in range(self.line_number):\n",
    "            self.draw_line(draw, width, height)\n",
    "\n",
    "        # 绘制小圆点 10/100=10%的概率\n",
    "        self.draw_point(draw, 10, width, height)\n",
    "\n",
    "        # 保存图片\n",
    "#         captcha.save('captcha', format=self.format)\n",
    "        # 显示图片\n",
    "        captcha.show()\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    a = Captcha()\n",
    "    a.make_captcha()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
